package ya.ru.kolemik;

import static org.twdata.maven.mojoexecutor.MojoExecutor.*;

import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.PluginManager;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.configuration.PlexusConfigurationException;
import org.codehaus.plexus.util.xml.Xpp3Dom;

/**
 * Execute a set of plugins one-to-one in turn
 * 
 * <pre>
 *          <plugin>
 *               <groupId>ru.ya.kolemik</groupId>
 *               <artifactId>maven-aggregate-plugin</artifactId>
 *               <executions>
 *                   <execution>
 *                       <id>1</id>
 *                       <phase>package</phase>
 *                       <goals>
 *                          <goal>run</goal>
 *                       </goals>
 *                       <configuration>
 *                           <plugins>
 *                               <plugin>
 *                                   <artifactId>maven-dependency-plugin</artifactId>
 *                                   <groupId>org.apache.maven.plugins</groupId>
 *                                   <version>2.0</version>
 *                                   <goal>copy-dependencies</goal>
 *                                   <configuration>
 *                                       <outputDirectory>
 *                                          ${project.build.directory}/foo
 *                                       </outputDirectory>
 *                                   </configuration>
 *                               </plugin>
 *                               <plugin>
 *                                   <artifactId>maven-antrun-plugin</artifactId>
 *                                   <goal>run</goal>
 *                                   <configuration>
 *                                       <tasks>
 *                                           <echo>Hello from Ant!</echo>
 *                                       </tasks>
 *                                   </configuration>
 *                              </plugin>
 *                               <plugin>
 *                                   <artifactId>maven-dependency-plugin</artifactId>
 *                                   <groupId>org.apache.maven.plugins</groupId>
 *                                   <version>2.0</version>
 *                                   <goal>copy-dependencies</goal>
 *                                   <configuration>
 *                                       <outputDirectory>
 *                                          ${project.build.directory}/bar
 *                                       </outputDirectory>
 *                                   </configuration>
 *                               </plugin>
 *                           </plugins>
 *                       </configuration>
 *                  </execution>
 *               </executions>
 *           </plugin>
 * </pre>
 * 
 * @author kolemik
 * @goal run
 */
public class MavenAggregatePlugin extends AbstractMojo {

/*

 */
    
    
    /**
     * Plugins, that must be executed one-to-one in turn
     * You can specify as much plugins as you need with optional configuration
     * 
     * @parameter expression="${package.plugins}" @required
     */
    private Plugin[] plugins;
    
    /**
     * The Maven Project Object
     * 
     * @parameter expression="${project}"
     * @required
     * @readonly
     */
    protected MavenProject project;
    
    /**
     * The Maven Session Object
     * 
     * @parameter expression="${session}"
     * @required
     * @readonly
     */
    protected MavenSession session;
    
    /**
     * The Maven PluginManager Object
     * 
     * @component
     * @required
     */
    protected PluginManager pluginManager;
    
    public void execute() throws MojoExecutionException, MojoFailureException {
        
        getLog().info("Start executing plugins");
        int counter = 1;
        for (Plugin plugin : plugins) {
            getLog().info(
                    "Start executing plugin " + plugin.getGroupId() + "."
                            + plugin.getArtifactId() + " " + counter++ + " of "
                            + plugins.length);
            Xpp3Dom configuration = null;
            if (plugin.getConfiguration() != null) {
                getLog().info(
                        "Plugin configuration exists:\n"
                                + getConfiguration(plugin.getConfiguration())
                                        .toString());
                configuration = getConfiguration(plugin
                        .getConfiguration());
            } else {
                getLog().info("Plugin configuration not exists");
            }
            checkRequiredFields(plugin);
            executeMojo(plugin(groupId(plugin.getGroupId()), artifactId(plugin
                    .getArtifactId()), version(plugin.getVersion())),
                    goal(plugin.getGoal()), configuration, executionEnvironment(project,
                            session, pluginManager));
            getLog().info(
                    "Finish executing plugin " + plugin.getGroupId() + "."
                            + plugin.getArtifactId());
        }
        getLog().info("Finish executing plugins");
        
    }
    
    public MavenProject getProject() {
        return project;
    }

    public void setProject(MavenProject project) {
        this.project = project;
    }

    public MavenSession getSession() {
        return session;
    }

    public void setSession(MavenSession session) {
        this.session = session;
    }

    public PluginManager getPluginManager() {
        return pluginManager;
    }

    public void setPluginManager(PluginManager pluginManager) {
        this.pluginManager = pluginManager;
    }

    private void checkRequiredFields(Plugin p) throws MojoExecutionException {
        if (p.getArtifactId() == null)
            throw new MojoExecutionException("You must specify artifactId");
        if (p.getGoal() == null)
            throw new MojoExecutionException("You must specify goal");
    }

    /**
     * @param p_conf
     * @return
     */
    public static Xpp3Dom getConfiguration(PlexusConfiguration p_conf) {
        Xpp3Dom root = new Xpp3Dom("configuration");
        for (PlexusConfiguration c : p_conf.getChildren()) {
            root.addChild(getSubConfiguration(c));
        }
        return root;
    }
    
    /**
     * @param p_conf
     * @return
     */
    private static Xpp3Dom getSubConfiguration(PlexusConfiguration p_conf) {
        Xpp3Dom dom = new Xpp3Dom(p_conf.getName());
        if (p_conf.getChildCount() == 0) {
            try {
                dom.setValue(p_conf.getValue());
            } catch (PlexusConfigurationException e) {
            }
        }
        for (PlexusConfiguration c : p_conf.getChildren()) {
            dom.addChild(getSubConfiguration(c));
        }
        for (String attrName : p_conf.getAttributeNames()) {
            try {
                dom.setAttribute(attrName, p_conf.getAttribute(attrName));
            } catch (PlexusConfigurationException e) {
            }
        }
        return dom;
    }
}
